//import org.apache.commons.lang.StringUtils;
//
//import java.sql.*;
//import java.util.*;
//
//public class JdbcHelper {
//
//    private static Map<String, List<String>> columnNameCache = new HashMap<String, List<String>>();
//    private static Map<String,Map<String, String>> tableMeta = new HashMap<>();
//
//    static {
//        try {
//            Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
////            Enumeration<Driver> drivers = DriverManager.getDrivers();
////            while (drivers.hasMoreElements()) {
////                Driver driver = drivers.nextElement();
////                if (driver.getClass().getSimpleName().equals("IgniteJdbcDriver") ) {
////                    DriverManager.deregisterDriver(driver);
////                }
////            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    public static Connection getConnection() {
//        try {
//            return DriverManager.getConnection("jdbc:ignite:thin://10.90.5.17");
//        } catch (SQLException e) {
//            throw new RuntimeException(e);
//        }
//    }
//
//    static {
//        Connection connection = getConnection();
//        try {
//            DatabaseMetaData databaseMetaData = connection.getMetaData();
//            ResultSet tableRet = databaseMetaData.getTables(null, "%", "%", new String[]{"TABLE"});
//            while(tableRet.next()) {
//                String tableName = tableRet.getString("TABLE_NAME");
//                tableMeta.put(tableName, new HashMap<>());
//                ResultSet colRet = databaseMetaData.getColumns(null, "%", tableName, "%");
//                while(colRet.next()) {
//                    String columnName = colRet.getString("COLUMN_NAME");
//                    String columnType = colRet.getString("TYPE_NAME");
//                    tableMeta.get(tableName).put(columnName, columnType);
//                }
//            }
//            System.out.println(JsonHelper.toMap(tableMeta));
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                connection.close();
//            } catch (Exception ignored) {
//            }
//        }
//    }
//
//    public static String getColumnType(String tableName, String columnName) {
//        return tableMeta.get(tableName).get(columnName);
//    }
//
//    public static boolean isDatetimeColumn(String tableName, String columnName) {
//        return Objects.equals(getColumnType(tableName, columnName), "DATETIME");
//    }
//
//    public static boolean containsColumn(String tableName, String columnName) {
//        return tableMeta.get(tableName).containsKey(columnName);
//    }
//
//    /**
//     * Execute an SQL query
//     * @param sql sql
//     * @return The query resultSet
//     */
//    public static <T> T executeQuery(MySQLCallback<T> callback, String sql, Object ... params) throws Exception {
//        Connection connection = null;
//        PreparedStatement pst = null;
//        ResultSet rs = null;
//        try {
//            connection = getConnection();
//            pst = connection.prepareStatement(sql);
//            int index = 0;
//
//            if (params != null) {
//                for (Object param : params) {
//                    pst.setObject(++index, param);
//                }
//            }
//
//            rs = pst.executeQuery();
//            if (callback != null) {
//                return callback.executeQuery(rs);
//            }
//        } finally {
//            close(rs);
//            close(pst);
//            close(connection);
//        }
//        return null;
//    }
//
//    public static void close(ResultSet rs) {
//        if (rs != null) {
//            try {
//                rs.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//    public static void close(Statement st) {
//        if (st != null) {
//            try {
//                st.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//    public static void close(Connection connection) {
//        if (connection != null) {
//            try {
//                connection.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//    public static void rollback(Connection connection) {
//        if (connection != null) {
//            try {
//                connection.rollback();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//    public static List<String> getColumns(ResultSet rs, String sql) {
//        String s = StringUtils.substringBefore(sql, "where").trim();
//        List<String> columns = columnNameCache.get(s);
//        if (columns == null || columns.isEmpty()) {
//            columns = new ArrayList<>();
//            try {
//                ResultSetMetaData metaData = rs.getMetaData();
//                int columnCount = metaData.getColumnCount();
//                for (int i = 1; i <= columnCount; i++) {
//                    columns.add(metaData.getColumnName(i));
//                }
//                columnNameCache.put(s, columns);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        return columns;
//    }
//
//
//
//    public interface MySQLCallback<T> {
//        T executeQuery(final ResultSet rs) throws Exception;
//    }
//
//    public static Map findFirst(final String sql, Object... args) {
//        try {
//            return executeQuery(rs -> {
//                List<String> columns = getColumns(rs, sql);
//                Map<String, Object> data = null;
//                if (rs.next()) {
//                    data = new HashMap<>();
//                    for (int i = 1; i <= columns.size(); i++) {
//                        data.put(columns.get(i - 1), rs.getObject(i));
//                    }
//                }
//                return data;
//            }, sql, args);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }
//
//    public static List<Map> find(final String sql, Object... args) {
//        try {
//            return executeQuery(rs -> {
//                List<String> columns = getColumns(rs, sql);
//                List<Map> data = new ArrayList<Map>();
//                while (rs.next()) {
//                    Map<String, Object> map = new HashMap<String, Object>();
//                    for (int i = 1; i <= columns.size(); i++) {
//                        map.put(columns.get(i - 1), rs.getObject(i));
//                    }
//                    data.add(map);
//                }
//                return data;
//            }, sql, args);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }
//
//    public static <T> List<T> find(final Class<T> cls, String sql, Object... args) {
//        final String realSql = String.format("select * from %s where %s", cls.getSimpleName(), sql);
//        try {
//            return executeQuery(rs -> {
//                List<String> columns = getColumns(rs, realSql);
//                List<T> data = new ArrayList<>();
//                while (rs.next()) {
//                    Map<String, Object> map = new HashMap<>();
//                    for (int i = 1; i <= columns.size(); i++) {
//                        map.put(columns.get(i - 1), rs.getObject(i));
//                    }
//                    data.add(JsonHelper.restore(map, cls));
//                }
//                return data;
//            }, realSql, args);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }
//
//    public static <T> List<T> findAll(final Class<T> cls) {
//        final String realSql = String.format("select * from %s", cls.getSimpleName());
//        try {
//            return executeQuery(rs -> {
//                List<String> columns = getColumns(rs, realSql);
//                List<T> data = new ArrayList<>();
//                while (rs.next()) {
//                    Map<String, Object> map = new HashMap<>();
//                    for (int i = 1; i <= columns.size(); i++) {
//                        map.put(columns.get(i - 1), rs.getObject(i));
//                    }
//                    data.add(JsonHelper.restore(map, cls));
//                }
//                return data;
//            }, realSql, null);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }
//
//    public static <T> T findById(final Class<T> cls, final long id) {
//        return JsonHelper.restore(findFirst(String.format("select * from %s.%s where id=%s", cls.getSimpleName(), cls.getSimpleName(), id)), cls);
//    }
//
//
//    public static <T> T findFirst(final Class<T> cls, final String sql, Object... args) {
//        return JsonHelper.restore(findFirst(String.format("select * from %s where %s", cls.getSimpleName(), sql), args), cls);
//    }
//
//    public static <T> long count(final Class<T> cls,String sql, Object... args) throws Exception {
//        final String realSql = String.format("select count(*) as total from %s where %s", cls.getSimpleName(), sql);
//        Connection connection = null;
//        PreparedStatement pst = null;
//        ResultSet rs = null;
//
//            try {
//            connection = getConnection();
//            pst = connection.prepareStatement(realSql, Statement.RETURN_GENERATED_KEYS);
//            int index = 0;
//
//            if (args != null) {
//                for (Object param : args) {
//                    pst.setObject(++index, param);
//                }
//            }
//            rs = pst.executeQuery();
//            while(rs.next()){
//                return rs.getInt("total");
//            }
//        } finally {
//            close(rs);
//            close(pst);
//            close(connection);
//        }
//        return 0l;
//    }
//
////    public long save(Object object) throws Exception {
////        Class cls = object.getClass();
////        String tableName = cls.getSimpleName();
////        List setKeys = Arrays.asList(cls.getDeclaredFields()).stream().map(Field::getName).collect(Collectors.toList());
////
////        Long id;
////        if (setKeys.contains("id") && (id = (Long)cls.getDeclaredField("id").get(object)) != null) {
////            List<String> signs = new ArrayList<>();
////            List<Object> values = new ArrayList<>();
////            for (Object key : setKeys) {
////                if (!Objects.equals(key, "id") && containsColumn(tableName, (String) key)) {
////                    signs.add(key + "=?");
////                    Object value = cls.getDeclaredField((String)key).get(object);
////                    values.add(isDatetimeColumn(tableName, key.toString()) && value instanceof Long ? new Date((Long)value) : value);
////                }
////            }
////
////            String sql = "update " + tableName + " set " + StringUtils.join(signs, ",") + " where id=" + id;
////            return executeUpdate(sql, values.toArray(new Object[values.size()]));
////        } else {
////            List<String> signs = new ArrayList<>();
////            List<String> keys = new ArrayList<>();
////            List<Object> values = new ArrayList<>();
////            for (Object key : setKeys) {
////                if (!Objects.equals(key, "id") && containsColumn(tableName, (String) key)) {
////                    signs.add("?");
////                    keys.add((String)key);
////                    Object value = cls.getDeclaredField((String)key).get(object);
////                    values.add(isDatetimeColumn(tableName, key.toString()) && value instanceof Long ? new Date((Long)value) : value);
////                }
////            }
////
////            String sql = "insert into " + tableName + "(" + StringUtils.join(keys, ",") + ")value(" + StringUtils.join(signs, ",") + ")";
////            return executeUpdateResponse(sql, values.toArray(new Object[values.size()]));
////        }
////    }
//
//}